/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.di.ban.jr.rest.global;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.ac.iie.di.ban.jr.rest.config.ConfigureUtil;
import cn.ac.iie.di.datadock.rdata.exchange.client.core.REFieldType;
import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import static cn.ac.iie.di.datadock.rdata.exchange.client.core.REFieldType.Struct;


/**
 *
 * @author QJP
 */
public class GlobalParas {

    public static Logger LOG = Logger.getLogger(GlobalParas.class);

    //properties name
    public final static String LOG4_CONFIGURATION = "log4j.properties";
    public final static String DEFAULT_CONFIGURATION = "configure.properties";

    //configuration.properties parameters

    public static String REST_SERVER_IP = "";
    public static Integer REST_SERVER_PORT = 0;
    public static Integer REST_SERVER_PARALLEL_SIZE = 0;

    public static String FILE_DIR = "";
    public static Integer FILE_SIZE = 5;
    public static Integer FILE_TIMEOUT = 5;

    public static List<Object> DATA_COLUMN_TYPE = null;
    public static HashMap<String, String> COLUMN_TYPE_MAP = null;

    public static String CONSUMER_NAMESERVER = "";
    public static List<Object> CONSUMER_DATATYPE_TOPIC = null;
    public static HashMap<String, String> CONSUMER_DATATYPE_TOPIC_MAP = null;

    public static List<String> COLUMNS_NAME_LIST;
    public static List<REFieldType> COLUMNS_TYPE_LIST;

    private static volatile GlobalParas instanceDefConf;

    public GlobalParas(String confPropertiesName) throws ConfigurationException {
        String confPropertiesPath = ClassLoader.getSystemClassLoader().getResource(confPropertiesName).getFile();
        ConfigureUtil configureUtil = new ConfigureUtil();
        FileBasedConfiguration configuration = configureUtil.initConfiguration(confPropertiesPath);
        if (confPropertiesName.equals(DEFAULT_CONFIGURATION)) {
            initConf(configuration);
        }
    }

    public static GlobalParas getIstance(String confPropertiesName) throws ConfigurationException {
        if (confPropertiesName.equals(DEFAULT_CONFIGURATION)) {
            if (instanceDefConf == null) {
                synchronized (GlobalParas.class) {
                    if (instanceDefConf == null) {
                        instanceDefConf = new GlobalParas(confPropertiesName);
                    }
                }
            }
            return instanceDefConf;
        }
        else {
            LOG.error("Could Not Find Configuration: " + confPropertiesName);
            return null;
        }
    }

    public static void initConf(FileBasedConfiguration configuration) {

        PropertyConfigurator.configure(ClassLoader.getSystemClassLoader().getResource(LOG4_CONFIGURATION));

        REST_SERVER_IP = configuration.getString("rest.server.ip");
        REST_SERVER_PORT = configuration.getInt("rest.server.port");
        REST_SERVER_PARALLEL_SIZE = configuration.getInt("rest.server.parallel_size");

        FILE_DIR = configuration.getString("file.dir");
        if (!FILE_DIR.endsWith("/")) {
            FILE_DIR += "/";
        }
        FILE_SIZE = configuration.getInt("file.size");
        FILE_TIMEOUT = configuration.getInt("file.timeout");

        DATA_COLUMN_TYPE = new ArrayList<>();
        DATA_COLUMN_TYPE = configuration.getList("data.column.type");
        COLUMN_TYPE_MAP = new HashMap<>();
        COLUMN_TYPE_MAP = initColumnTypeMap();

        CONSUMER_NAMESERVER = configuration.getString("consumer.nameserver");
        CONSUMER_DATATYPE_TOPIC = configuration.getList("consumer.datatype.topic");

        CONSUMER_DATATYPE_TOPIC_MAP = new HashMap<>();
        CONSUMER_DATATYPE_TOPIC_MAP = initDatatypeTopic();

        GlobalParas.COLUMNS_NAME_LIST = new ArrayList<>();
        GlobalParas.COLUMNS_TYPE_LIST = new ArrayList<>();
        initFieldMap();
    }

    private static HashMap<String, String> initColumnTypeMap() {
        HashMap<String, String> hashMap = new HashMap<>();
        for (Object topicGroup: DATA_COLUMN_TYPE) {
            hashMap.put(String.valueOf(topicGroup).split(":")[0], String.valueOf(topicGroup).split(":")[1]);
        }
        return hashMap;
    }

    private static void initFieldMap() {
        for(Object field: DATA_COLUMN_TYPE) {
            LOG.debug(field);
            switch (((String)field).split(":")[1]) {
                case "int": {
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.Int);
                    break;
                }
                case "timestamp":
                case "long": {
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.Long);
                    break;
                }
                case "string": {
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.String);
                    break;
                }
                case "strings": {
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.Strings);
                    break;
                }
                case "struct": {
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.Struct);
                    break;
                }
                case "structs": {
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.Structs);
                    break;
                }
                case "double":{
                    COLUMNS_NAME_LIST.add(((String) field).split(":")[0]);
                    COLUMNS_TYPE_LIST.add(REFieldType.Double);
                    break;
                }
                default: {
                    LOG.error("not find field type: " + ((String)field).split(":")[1]);
                    break;
                }
            }
        }
    }

    private static HashMap<String, String> initDatatypeTopic() {
        HashMap<String, String> hashMap = new HashMap<>();
        for (Object object: CONSUMER_DATATYPE_TOPIC) {
            hashMap.put(String.valueOf(object).split(":")[0], String.valueOf(object).split(":")[1]);
        }
        return hashMap;
    }
}
